import {
	columeHeader_word,
	columeHeader_word_index,
	luckysheetdefaultFont,
} from "../controllers/constant";
import menuButton from "../controllers/menuButton";
import { isdatatype, isdatatypemulti } from "../global/datecontroll";
import { hasChinaword, isRealNum } from "../global/validate";
import Store from "../store";
import locale from "../locale/locale";
import numeral from "numeral";
// import method from '../global/method';

/**
 * Common tool methods
 */

/**
 * Determine whether a string is in standard JSON format
 * @param {String} str
 */
function isJsonString(str) {
	try {
		if (typeof JSON.parse(str) == "object") {
			return true;
		}
	} catch (e) {}
	return false;
}

/**
 * extend two objects
 * @param {Object } jsonbject1
 * @param {Object } jsonbject2
 */
function common_extend(jsonbject1, jsonbject2) {
	let resultJsonObject = {};

	for (let attr in jsonbject1) {
		resultJsonObject[attr] = jsonbject1[attr];
	}

	for (let attr in jsonbject2) {
		// undefined is equivalent to no setting
		if (jsonbject2[attr] == undefined) {
			continue;
		}
		resultJsonObject[attr] = jsonbject2[attr];
	}

	return resultJsonObject;
}

// 替换temp中的${xxx}为指定内容 ,temp:字符串，这里指html代码，dataarry：一个对象{"xxx":"替换的内容"}
// 例：luckysheet.replaceHtml("${image}",{"image":"abc","jskdjslf":"abc"})   ==>  abc
function replaceHtml(temp, dataarry) {
	return temp.replace(/\$\{([\w]+)\}/g, function(s1, s2) {
		let s = dataarry[s2];
		if (typeof s != "undefined") {
			return s;
		} else {
			return s1;
		}
	});
}

//获取数据类型
function getObjType(obj) {
	let toString = Object.prototype.toString;

	let map = {
		"[object Boolean]": "boolean",
		"[object Number]": "number",
		"[object String]": "string",
		"[object Function]": "function",
		"[object Array]": "array",
		"[object Date]": "date",
		"[object RegExp]": "regExp",
		"[object Undefined]": "undefined",
		"[object Null]": "null",
		"[object Object]": "object",
	};

	// if(obj instanceof Element){
	//     return 'element';
	// }

	return map[toString.call(obj)];
}

//获取当前日期时间
function getNowDateTime(format) {
	let now = new Date();
	let year = now.getFullYear(); //得到年份
	let month = now.getMonth(); //得到月份
	let date = now.getDate(); //得到日期
	let day = now.getDay(); //得到周几
	let hour = now.getHours(); //得到小时
	let minu = now.getMinutes(); //得到分钟
	let sec = now.getSeconds(); //得到秒

	month = month + 1;
	if (month < 10) month = "0" + month;
	if (date < 10) date = "0" + date;
	if (hour < 10) hour = "0" + hour;
	if (minu < 10) minu = "0" + minu;
	if (sec < 10) sec = "0" + sec;

	let time = "";

	//日期
	if (format == 1) {
		time = year + "-" + month + "-" + date;
	}
	//日期时间
	else if (format == 2) {
		time =
			year + "-" + month + "-" + date + " " + hour + ":" + minu + ":" + sec;
	}

	return time;
}

//颜色 16进制转rgb
function hexToRgb(hex) {
	let color = [],
		rgb = [];
	hex = hex.replace(/#/, "");

	if (hex.length == 3) {
		// 处理 "#abc" 成 "#aabbcc"
		let tmp = [];

		for (let i = 0; i < 3; i++) {
			tmp.push(hex.charAt(i) + hex.charAt(i));
		}

		hex = tmp.join("");
	}

	for (let i = 0; i < 3; i++) {
		color[i] = "0x" + hex.substr(i + 2, 2);
		rgb.push(parseInt(Number(color[i])));
	}

	return "rgb(" + rgb.join(",") + ")";
}

//颜色 rgb转16进制
function rgbTohex(color) {
	let rgb;

	if (color.indexOf("rgba") > -1) {
		rgb = color
			.replace("rgba(", "")
			.replace(")", "")
			.split(",");
	} else {
		rgb = color
			.replace("rgb(", "")
			.replace(")", "")
			.split(",");
	}

	let r = parseInt(rgb[0]);
	let g = parseInt(rgb[1]);
	let b = parseInt(rgb[2]);

	let hex = "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);

	return hex;
}

//列下标  字母转数字
function ABCatNum(a) {
	// abc = abc.toUpperCase();

	// let abc_len = abc.length;
	// if (abc_len == 0) {
	//     return NaN;
	// }

	// let abc_array = abc.split("");
	// let wordlen = columeHeader_word.length;
	// let ret = 0;

	// for (let i = abc_len - 1; i >= 0; i--) {
	//     if (i == abc_len - 1) {
	//         ret += columeHeader_word_index[abc_array[i]];
	//     }
	//     else {
	//         ret += Math.pow(wordlen, abc_len - i - 1) * (columeHeader_word_index[abc_array[i]] + 1);
	//     }
	// }

	// return ret;
	if (a == null || a.length == 0) {
		return NaN;
	}
	var str = a.toLowerCase().split("");
	var num = 0;
	var al = str.length;
	var getCharNumber = function(charx) {
		return charx.charCodeAt() - 96;
	};
	var numout = 0;
	var charnum = 0;
	for (var i = 0; i < al; i++) {
		charnum = getCharNumber(str[i]);
		numout += charnum * Math.pow(26, al - i - 1);
	}
	// console.log(a, numout-1);
	if (numout == 0) {
		return NaN;
	}
	return numout - 1;
}

//列下标  数字转字母
function chatatABC(n) {
	// let wordlen = columeHeader_word.length;

	// if (index < wordlen) {
	//     return columeHeader_word[index];
	// }
	// else {
	//     let last = 0, pre = 0, ret = "";
	//     let i = 1, n = 0;

	//     while (index >= (wordlen / (wordlen - 1)) * (Math.pow(wordlen, i++) - 1)) {
	//         n = i;
	//     }

	//     let index_ab = index - (wordlen / (wordlen - 1)) * (Math.pow(wordlen, n - 1) - 1);//970
	//     last = index_ab + 1;

	//     for (let x = n; x > 0; x--) {
	//         let last1 = last, x1 = x;//-702=268, 3

	//         if (x == 1) {
	//             last1 = last1 % wordlen;

	//             if (last1 == 0) {
	//                 last1 = 26;
	//             }

	//             return ret + columeHeader_word[last1 - 1];
	//         }

	//         last1 = Math.ceil(last1 / Math.pow(wordlen, x - 1));
	//         //last1 = last1 % wordlen;
	//         ret += columeHeader_word[last1 - 1];

	//         if (x > 1) {
	//             last = last - (last1 - 1) * wordlen;
	//         }
	//     }
	// }

	var orda = "a".charCodeAt(0);

	var ordz = "z".charCodeAt(0);

	var len = ordz - orda + 1;

	var s = "";

	while (n >= 0) {
		s = String.fromCharCode((n % len) + orda) + s;

		n = Math.floor(n / len) - 1;
	}

	return s.toUpperCase();
}

function ceateABC(index) {
	let wordlen = columeHeader_word.length;

	if (index < wordlen) {
		return columeHeader_word;
	} else {
		let relist = [];
		let i = 2,
			n = 0;

		while (index < (wordlen / (wordlen - 1)) * (Math.pow(wordlen, i) - 1)) {
			n = i;
			i++;
		}

		for (let x = 0; x < n; x++) {
			if (x == 0) {
				relist = relist.concat(columeHeader_word);
			} else {
				relist = relist.concat(createABCdim(x), index);
			}
		}
	}
}

function createABCdim(x, count) {
	let chwl = columeHeader_word.length;

	if (x == 1) {
		let ret = [];
		let c = 0,
			con = true;

		for (let i = 0; i < chwl; i++) {
			let b = columeHeader_word[i];

			for (let n = 0; n < chwl; n++) {
				let bq = b + columeHeader_word[n];
				ret.push(bq);
				c++;

				if (c > index) {
					return ret;
				}
			}
		}
	} else if (x == 2) {
		let ret = [];
		let c = 0,
			con = true;

		for (let i = 0; i < chwl; i++) {
			let bb = columeHeader_word[i];

			for (let w = 0; w < chwl; w++) {
				let aa = columeHeader_word[w];

				for (let n = 0; n < chwl; n++) {
					let bqa = bb + aa + columeHeader_word[n];
					ret.push(bqa);
					c++;

					if (c > index) {
						return ret;
					}
				}
			}
		}
	}
}

/**
 * 计算字符串字节长度
 * @param {*} val 字符串
 * @param {*} subLen 要截取的字符串长度
 */
function getByteLen(val, subLen) {
	if (subLen === 0) {
		return "";
	}

	if (val == null) {
		return 0;
	}

	let len = 0;
	for (let i = 0; i < val.length; i++) {
		let a = val.charAt(i);

		if (a.match(/[^\x00-\xff]/gi) != null) {
			len += 2;
		} else {
			len += 1;
		}

		if (isRealNum(subLen) && len === ~~subLen) {
			return val.substring(0, i);
		}
	}

	return len;
}

//数组去重
function ArrayUnique(dataArr) {
	let result = [];
	let obj = {};
	if (dataArr.length > 0) {
		for (let i = 0; i < dataArr.length; i++) {
			let item = dataArr[i];
			if (!obj[item]) {
				result.push(item);
				obj[item] = 1;
			}
		}
	}
	return result;
}

//获取字体配置
function luckysheetfontformat(format) {
	let fontarray = locale().fontarray;
	if (getObjType(format) == "object") {
		let font = "";

		//font-style
		if (format.it == "0" || format.it == null) {
			font += "normal ";
		} else {
			font += "italic ";
		}

		//font-variant
		font += "normal ";

		//font-weight
		if (format.bl == "0" || format.bl == null) {
			font += "normal ";
		} else {
			font += "bold ";
		}

		//font-size/line-height
		if (!format.fs) {
			font += Store.defaultFontSize + "pt ";
		} else {
			font += Math.ceil(format.fs) + "pt ";
		}

		if (!format.ff) {
			font +=
				fontarray[0] +
				', "Helvetica Neue", Helvetica, Arial, "PingFang SC", "Hiragino Sans GB", "Heiti SC", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif';
		} else {
			let fontfamily = null;
			let fontjson = locale().fontjson;
			if (isdatatypemulti(format.ff)["num"]) {
				fontfamily = fontarray[parseInt(format.ff)];
			} else {
				// fontfamily = fontarray[fontjson[format.ff]];
				fontfamily = format.ff;

				fontfamily = fontfamily.replace(/"/g, "").replace(/'/g, "");

				if (fontfamily.indexOf(" ") > -1) {
					fontfamily = '"' + fontfamily + '"';
				}

				if (
					fontfamily != null &&
					document.fonts &&
					!document.fonts.check("12px " + fontfamily)
				) {
					menuButton.addFontTolist(fontfamily);
				}
			}

			if (fontfamily == null) {
				fontfamily = fontarray[0];
			}

			font +=
				fontfamily +
				', "Helvetica Neue", Helvetica, Arial, "PingFang SC", "Hiragino Sans GB", "Heiti SC", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif';
		}

		return font;
	} else {
		return luckysheetdefaultFont();
	}
}

//右键菜单
function showrightclickmenu($menu, x, y) {
	let winH = $(window).height(),
		winW = $(window).width();
	let menuW = $menu.width(),
		menuH = $menu.height();
	let top = y,
		left = x;

	if (x + menuW > winW) {
		left = x - menuW;
	}

	if (y + menuH > winH) {
		top = y - menuH;
	}

	if (top < 0) {
		top = 0;
	}

	$menu.css({ top: top, left: left }).show();
}

//单元格编辑聚焦
function luckysheetactiveCell() {
	if (!!Store.fullscreenmode) {
		setTimeout(function() {
			// need preventScroll:true,fix Luckysheet has been set top, and clicking the cell will trigger the scrolling problem
			const input = document.getElementById("luckysheet-rich-text-editor");
			input.focus({ preventScroll: true });
			$("#luckysheet-rich-text-editor").select();
			// $("#luckysheet-rich-text-editor").focus().select();
		}, 50);
	}
}

//单元格编辑聚焦
function luckysheetContainerFocus() {
	// $("#" + Store.container).focus({
	//     preventScroll: true
	// });

	// fix jquery error: Uncaught TypeError: ((n.event.special[g.origType] || {}).handle || g.handler).apply is not a function
	// $("#" + Store.container).attr("tabindex", 0).focus();

	// need preventScroll:true,fix Luckysheet has been set top, and clicking the cell will trigger the scrolling problem
	document.getElementById(Store.container).focus({ preventScroll: true });
}

//数字格式
function numFormat(num, type) {
	if (
		num == null ||
		isNaN(parseFloat(num)) ||
		hasChinaword(num) ||
		num == -Infinity ||
		num == Infinity
	) {
		return null;
	}

	let floatlen = 6,
		ismustfloat = false;
	if (type == null || type == "auto") {
		if (num < 1) {
			floatlen = 6;
		} else {
			floatlen = 1;
		}
	} else {
		if (isdatatype(type) == "num") {
			floatlen = parseInt(type);
			ismustfloat = true;
		} else {
			floatlen = 6;
		}
	}

	let format = "",
		value = null;
	for (let i = 0; i < floatlen; i++) {
		format += "0";
	}

	if (!ismustfloat) {
		format = "[" + format + "]";
	}

	if (num >= 1e21) {
		value = parseFloat(numeral(num).value());
	} else {
		value = parseFloat(numeral(num).format("0." + format));
	}

	return value;
}

function numfloatlen(n) {
	if (n != null && !isNaN(parseFloat(n)) && !hasChinaword(n)) {
		let value = numeral(n).value();
		let lens = value.toString().split(".");

		if (lens.length == 1) {
			lens = 0;
		} else {
			lens = lens[1].length;
		}

		return lens;
	} else {
		return null;
	}
}

//二级菜单显示位置
function mouseclickposition($menu, x, y, p) {
	let winH = $(window).height(),
		winW = $(window).width();
	let menuW = $menu.width(),
		menuH = $menu.height();
	let top = y,
		left = x;

	if (p == null) {
		p = "lefttop";
	}

	if (p == "lefttop") {
		$menu.css({ top: y, left: x }).show();
	} else if (p == "righttop") {
		$menu.css({ top: y, left: x - menuW }).show();
	} else if (p == "leftbottom") {
		$menu.css({ bottom: winH - y - 12, left: x }).show();
	} else if (p == "rightbottom") {
		$menu.css({ bottom: winH - y - 12, left: x - menuW }).show();
	}
}

/**
 * 元素选择器
 * @param {String}  selector css选择器
 * @param {String}  context  指定父级DOM
 */
function $$(selector, context) {
	context = context || document;
	var elements = context.querySelectorAll(selector);
	return elements.length == 1
		? Array.prototype.slice.call(elements)[0]
		: Array.prototype.slice.call(elements);
}

/**
 * 串行加载指定的脚本
 * 串行加载[异步]逐个加载，每个加载完成后加载下一个
 * 全部加载完成后执行回调
 * @param {Array|String}  scripts 指定要加载的脚本
 * @param {Object} options 属性设置
 * @param {Function} callback 成功后回调的函数
 * @return {Array} 所有生成的脚本元素对象数组
 */

function seriesLoadScripts(scripts, options, callback) {
	if (typeof scripts !== "object") {
		var scripts = [scripts];
	}
	var HEAD =
		document.getElementsByTagName("head")[0] || document.documentElement;
	var s = [];
	var last = scripts.length - 1;
	//递归
	var recursiveLoad = function(i) {
		s[i] = document.createElement("script");
		s[i].setAttribute("type", "text/javascript");
		// Attach handlers for all browsers
		// 异步
		s[i].onload = s[i].onreadystatechange = function() {
			if (
				!(/*@cc_on!@*/ 0) ||
				this.readyState === "loaded" ||
				this.readyState === "complete"
			) {
				this.onload = this.onreadystatechange = null;
				this.parentNode.removeChild(this);
				if (i !== last) {
					recursiveLoad(i + 1);
				} else if (typeof callback === "function") {
					callback();
				}
			}
		};
		// 同步
		s[i].setAttribute("src", scripts[i]);

		// 设置属性
		if (typeof options === "object") {
			for (var attr in options) {
				s[i].setAttribute(attr, options[attr]);
			}
		}

		HEAD.appendChild(s[i]);
	};
	recursiveLoad(0);
}

/**
 * 并行加载指定的脚本
 * 并行加载[同步]同时加载，不管上个是否加载完成，直接加载全部
 * 全部加载完成后执行回调
 * @param {Array|String}  scripts 指定要加载的脚本
 * @param {Object} options 属性设置
 * @param {Function} callback 成功后回调的函数
 * @return {Array} 所有生成的脚本元素对象数组
 */

function parallelLoadScripts(scripts, options, callback) {
	if (typeof scripts !== "object") {
		var scripts = [scripts];
	}
	var HEAD =
		document.getElementsByTagName("head")[0] || document.documentElement;
	var s = [];
	var loaded = 0;
	for (var i = 0; i < scripts.length; i++) {
		s[i] = document.createElement("script");
		s[i].setAttribute("type", "text/javascript");
		// Attach handlers for all browsers
		// 异步
		s[i].onload = s[i].onreadystatechange = function() {
			if (
				!(/*@cc_on!@*/ 0) ||
				this.readyState === "loaded" ||
				this.readyState === "complete"
			) {
				loaded++;
				this.onload = this.onreadystatechange = null;
				this.parentNode.removeChild(this);
				if (loaded === scripts.length && typeof callback === "function")
					callback();
			}
		};
		// 同步
		s[i].setAttribute("src", scripts[i]);

		// 设置属性
		if (typeof options === "object") {
			for (var attr in options) {
				s[i].setAttribute(attr, options[attr]);
			}
		}

		HEAD.appendChild(s[i]);
	}
}

/**
 * 动态添加css
 * @param {String}  url 指定要加载的css地址
 */
function loadLink(url) {
	var doc = document;
	var link = doc.createElement("link");
	link.setAttribute("rel", "stylesheet");
	link.setAttribute("type", "text/css");
	link.setAttribute("href", url);

	var heads = doc.getElementsByTagName("head");
	if (heads.length) {
		heads[0].appendChild(link);
	} else {
		doc.documentElement.appendChild(link);
	}
}

/**
 * 动态添加一组css
 * @param {String}  url 指定要加载的css地址
 */
function loadLinks(urls) {
	if (typeof urls !== "object") {
		urls = [urls];
	}
	if (urls.length) {
		urls.forEach((url) => {
			loadLink(url);
		});
	}
}

function transformRangeToAbsolute(txt1) {
	if (txt1 == null || txt1.length == 0) {
		return null;
	}

	let txtArray = txt1.split(",");
	let ret = "";
	for (let i = 0; i < txtArray.length; i++) {
		let txt = txtArray[i];
		let txtSplit = txt.split("!"),
			sheetName = "",
			rangeTxt = "";
		if (txtSplit.length > 1) {
			sheetName = txtSplit[0];
			rangeTxt = txtSplit[1];
		} else {
			rangeTxt = txtSplit[0];
		}

		let rangeTxtArray = rangeTxt.split(":");

		let rangeRet = "";
		for (let a = 0; a < rangeTxtArray.length; a++) {
			let t = rangeTxtArray[a];

			let row = t.replace(/[^0-9]/g, "");
			let col = t.replace(/[^A-Za-z]/g, "");
			let rangeTT = "";
			if (col != "") {
				rangeTT += "$" + col;
			}

			if (row != "") {
				rangeTT += "$" + row;
			}

			rangeRet += rangeTT + ":";
		}

		rangeRet = rangeRet.substr(0, rangeRet.length - 1);

		ret += sheetName + rangeRet + ",";
	}

	return ret.substr(0, ret.length - 1);
}

function openSelfModel(id, isshowMask = true) {
	let $t = $("#" + id)
			.find(".luckysheet-modal-dialog-content")
			.css("min-width", 300)
			.end(),
		myh = $t.outerHeight(),
		myw = $t.outerWidth();
	let winw = $(window).width(),
		winh = $(window).height();
	let scrollLeft = $(document).scrollLeft(),
		scrollTop = $(document).scrollTop();
	$t.css({
		left: (winw + scrollLeft - myw) / 2,
		top: (winh + scrollTop - myh) / 3,
	}).show();

	if (isshowMask) {
		$("#luckysheet-modal-dialog-mask").show();
	}
}

/**
 * 监控对象变更
 * @param {*} data
 */
// const createProxy = (data,list=[]) => {
//     if (typeof data === 'object' && data.toString() === '[object Object]') {
//       for (let k in data) {
//         if(list.includes(k)){
//             if (typeof data[k] === 'object') {
//               defineObjectReactive(data, k, data[k])
//             } else {
//               defineBasicReactive(data, k, data[k])
//             }
//         }
//       }
//     }
// }

const createProxy = (data, k, callback) => {
	if (!data.hasOwnProperty(k)) {
		console.info("No %s in data", k);
		return;
	}

	if (getObjType(data) === "object") {
		if (getObjType(data[k]) === "object" || getObjType(data[k]) === "array") {
			defineObjectReactive(data, k, data[k], callback);
		} else {
			defineBasicReactive(data, k, data[k], callback);
		}
	}
};

function defineObjectReactive(obj, key, value, callback) {
	// 递归
	obj[key] = new Proxy(value, {
		set(target, property, val, receiver) {
			setTimeout(() => {
				callback(target, property, val, receiver);
			}, 0);

			return Reflect.set(target, property, val, receiver);
		},
	});
}

function defineBasicReactive(obj, key, value, callback) {
	Object.defineProperty(obj, key, {
		enumerable: true,
		configurable: false,
		get() {
			return value;
		},
		set(newValue) {
			if (value === newValue) return;
			console.log(`发现 ${key} 属性 ${value} -> ${newValue}`);

			setTimeout(() => {
				callback(value, newValue);
			}, 0);

			value = newValue;
		},
	});
}

/**
 * Remove an item in the specified array
 * @param {array} array Target array
 * @param {string} item What needs to be removed
 */
function arrayRemoveItem(array, item) {
	array.some((curr, index, arr) => {
		if (curr === item) {
			arr.splice(index, 1);
			return curr === item;
		}
	});
}

/**
 * camel 形式的单词转换为 - 形式 如 fillColor -> fill-color
 * @param {string} camel camel 形式
 * @returns
 */
function camel2split(camel) {
	return camel.replace(/([A-Z])/g, function(all, group) {
		return "-" + group.toLowerCase();
	});
}

export {
	isJsonString,
	common_extend,
	replaceHtml,
	getObjType,
	getNowDateTime,
	hexToRgb,
	rgbTohex,
	ABCatNum,
	chatatABC,
	ceateABC,
	createABCdim,
	getByteLen,
	ArrayUnique,
	luckysheetfontformat,
	showrightclickmenu,
	luckysheetactiveCell,
	numFormat,
	numfloatlen,
	mouseclickposition,
	$$,
	seriesLoadScripts,
	parallelLoadScripts,
	loadLinks,
	luckysheetContainerFocus,
	transformRangeToAbsolute,
	openSelfModel,
	createProxy,
	arrayRemoveItem,
	camel2split,
};
